/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
/**
 * Software License, Version 1.0 Copyright 2003 The Trustees of Indiana
 * University. All rights reserved. Redistribution and use in source and binary
 * forms, with or without modification, are permitted provided that the
 * following conditions are met: 1) All redistributions of source code must
 * retain the above copyright notice, the list of authors in the original source
 * code, this list of conditions and the disclaimer listed in this license; 2)
 * All redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer listed in this license in the
 * documentation and/or other materials provided with the distribution; 3) Any
 * documentation included with all redistributions must include the following
 * acknowledgement: "This product includes software developed by the Community
 * Grids Lab. For further information contact the Community Grids Lab at
 * http://communitygrids.iu.edu/." Alternatively, this acknowledgement may
 * appear in the software itself, and wherever such third-party acknowledgments
 * normally appear. 4) The name Indiana University or Community Grids Lab or
 * NaradaBrokering, shall not be used to endorse or promote products derived
 * from this software without prior written permission from Indiana University.
 * For written permission, please contact the Advanced Research and Technology
 * Institute ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202. 5)
 * Products derived from this software may not be called NaradaBrokering, nor
 * may Indiana University or Community Grids Lab or NaradaBrokering appear in
 * their name, without prior written permission of ARTI. Indiana University
 * provides no reassurances that the source code provided does not infringe the
 * patent or any other intellectual property rights of any other entity. Indiana
 * University disclaims any liability to any recipient for claims brought by any
 * other entity based on infringement of intellectual property rights or
 * otherwise. LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH
 * NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY
 * GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF
 * INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS.
 * INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS",
 * "VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.
 * LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR
 * ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION
 * GENERATED USING SOFTWARE.
 */

package cgl.narada.transport.https;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Security;
import java.util.Properties;

import javax.net.ssl.SSLServerSocketFactory;

import org.apache.log4j.Logger;

import cgl.narada.transport.TransportException;
import cgl.narada.transport.sslHttpBase.Transport;
import cgl.narada.transport.sslHttpBase.TransportFactory;
import cgl.narada.util.proxy.WinProxyDetection;

/**
 * @author Hongbin Liu
 * @version 1.0
 */

public class HTTPSTransportFactoryImpl implements TransportFactory {

	final static Logger log = Logger.getLogger(HTTPSTransportFactoryImpl.class
			.getName());

	private ServerSocket m_serverSocket;
	private Properties m_defaultProperties = new Properties();
	private int m_port = 0; // HTTPSTransport.DEFAULT_HTTPS_PORT;
	private SSLServerSocketFactory m_serverSocketFactory = null;

	/**
	 * -----------------------------------------------------------------
	 */
	public Transport createTransportInstance() {
		// Currently just use JSSE implementation until WinINET is ready.
		Transport t = new HTTPSTransportImpl();
		t.setProperties(m_defaultProperties);
		return t;
	}

	/**
	 * -----------------------------------------------------------------
	 * Parameters: listenerport - The port to listen on truststore - Location of
	 * the trusted authorities database keystore - Location of the
	 * public/private key database truststorePassword - Password to the
	 * truststore keystorePassword - Password to the keystore username - Proxy
	 * authenticated user name. password - Proxy authenticated password.
	 * https.proxyHost - The location of the HTTPS proxy. Will try to auto
	 * detect from System properties if this does not exist. https.proxyPort -
	 * The location of the HTTPS proxy port. Will try to auto detect from System
	 * properties if this does not exist. secure - true | false. If false, will
	 * not do any real HTTPS.
	 */
	public void setProperties(Properties properties) {
		m_defaultProperties.putAll(properties);
		String val = properties.getProperty("listenerport");
		if (val != null && val.length() > 0) {
			try {
				m_port = Integer.parseInt(val);
			}
			catch (NumberFormatException e) {
				log.warn("Invalid listening port " + val
						+ " defaulting to port " + m_port);
			}
		}
		log.info("Will listen on port " + m_port);

		val = properties.getProperty("truststore");
		if (val != null && val.length() > 0) {
			System.getProperties().put("javax.net.ssl.trustStore", val);
			log.info("Setting truststore to " + val);
		}

		val = properties.getProperty("keystore");
		if (val != null && val.length() > 0) {
			System.getProperties().put("javax.net.ssl.keyStore", val);
			log.info("Setting keystore to " + val);
		}

		val = properties.getProperty("keystorePassword");
		if (val != null && val.length() > 0) {
			System.getProperties().put("javax.net.ssl.keyStorePassword", val);
			log.info("Setting keystore password to " + val);
		}

		val = properties.getProperty("truststorePassword");
		if (val != null && val.length() > 0) {
			System.getProperties().put("javax.net.ssl.trustStorePassword", val);
			log.info("Setting truststore password to " + val);
		}

		val = properties.getProperty("secure");
		if (val != null && val.equalsIgnoreCase("true")) {
			Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
			m_serverSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory
					.getDefault();

			log.info("Set to secure mode");
		}
		else {
			log.info("Set to unsecure mode");
		}
	}

	/**
	 * ----------------------------------------------------------------- Starts
	 * a listening socket.
	 */
	public void initialize() throws TransportException {
		try {
			if (m_serverSocketFactory == null) {
				m_serverSocket = new ServerSocket(m_port);
			}
			else {
				m_serverSocket = m_serverSocketFactory
						.createServerSocket(m_port);
			}
		}
		catch (Exception e) {
			throw new TransportException("IOException=" + e.getMessage());
		}

		String os = System.getProperty("os.name");

		if (os.toLowerCase().indexOf("windows") >= 0) {
			WinProxyDetection detection = new WinProxyDetection();
			String domain = detection.GetDomainWorkgroupName();
			String hostname = detection.GetHostName();
			log.debug("Detected windows domain: " + domain);
			log.debug("Detected windows hostname: " + hostname);
			m_defaultProperties.setProperty("domain", domain);
			m_defaultProperties.setProperty("hostname", hostname);
		}
		log.info("HTTPS Acceptor created on port " + m_port);
	}

	/**
	 * -----------------------------------------------------------------
	 */
	public Transport accept() throws TransportException {
		if (m_serverSocket == null) {
			throw new TransportException(
					"HTTPS Transport Factory not yet initialized");
		}
		try {
			Socket socket = m_serverSocket.accept();
			socket.setSoLinger(false, 0);
			socket.setTcpNoDelay(true);
			return new HTTPSTransportImpl(socket);

		}
		catch (IOException e) {
			throw new TransportException("IOException=" + e.getMessage());
		}
	}
}
